package top.whsu.FileClient;

import java.io.*;
import java.net.*;

public class Client {

    private String serverAddress;

    private int portNum;
    
    public Client(String serverAddress, int portNum) {
        this.serverAddress = serverAddress;
        this.portNum = portNum;
    }

    public void upload(String filePath) {
        File file = new File(filePath);
        this.upload(file);
    }

    public void upload(File file) {
        if (file.exists() && file.isFile()) {
            Socket socket = null;
            FileInputStream fin = null;
            try {
                fin = new FileInputStream(file);
                socket = new Socket(this.serverAddress, this.portNum);
                Logger logger = new Logger(socket.getInputStream(), fin.available());
                Uploader uploader = new Uploader(socket.getOutputStream(), fin);

                Thread t1 = new Thread(logger);
                Thread t2 = new Thread(uploader);

                t1.start();
                t2.start();

                t2.join();
                t1.join();

                socket.close();
                fin.close();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    class Logger implements Runnable {

        private DataInputStream logStream;

        private int fileSize;

        public Logger(InputStream inp, int fileSize) {
            this.logStream = new DataInputStream(inp);
            this.fileSize = fileSize;
        }

        public void run() {
            int a = 0;
            int percentage = 0;
            while (true) {
                try {
                    a = this.logStream.readInt();
                } catch (IOException e) {
                    System.out.printf("Abort due to Exception: %s\n%s\n", e.getClass(), e.getMessage());
                    break;
                }
                if (a==fileSize) {
                    System.out.println("Completed!");
                    break;
                } 
                else {
                    int nowPercentage = 100*a/fileSize;
                    if (percentage!=nowPercentage) {
                        percentage = nowPercentage;
                        System.out.printf("%d B of %d B transmitted, %f%%\n", a, fileSize, 100.0*a/fileSize);
                    }
                }
            }
        }
    }

    class Uploader implements Runnable {

        private OutputStream uploadStream;

        private FileInputStream fileInputStream;

        private byte[] buffer = new byte[1024];

        public Uploader(OutputStream uploadStream, FileInputStream fileInputStream) {
            this.uploadStream = uploadStream;
            this.fileInputStream = fileInputStream;
        }

        public void run() {
            int a = 0;
            try {
                while ((a=fileInputStream.read(buffer, 0, buffer.length)) != -1) {
                    uploadStream.write(buffer, 0, a);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
